﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PGMHelper;

namespace WSAP
{
    /***
     * 两悬壁柱，施加轴向力及水平力
     * i柱不考虑二阶效应，j柱考虑二阶效应
     * 使用AddRectConcreteColumn添加柱单元
     * 使用SetPDelta修改构件是否考虑二阶效应
     * 使用FixZ实现面约束
     * 使用DoLinearStaticAnalyze需将竖向力及水平力分开加载放可考虑二阶效应
     * 使用DoGeneralStaticAnalyze则可同时加载竖向力及水平力（带平衡条件）
    ****/

    /// <summary>
    /// 悬臂柱测试
    /// </summary>
    class WSAPCantileverColumn
    {
        /// <summary>
        ///  悬臂柱算例 线性加载 需分两步进行
        /// </summary>
        /// <param name="width"> 截面宽度 </param>
        /// <param name="height"> 截面高度 </param>
        /// <param name="length"> 构件长度 </param>
        /// <param name="horizontalLoadValue"> 水平荷载 </param>
        /// <param name="verticalLoadValue"> 竖向荷载 </param>
        /// <returns></returns>
        public static bool PDeltaExampleWithDoubleLinearAnalyze(double width, double height, double length, int meshNumber,
            double horizontalLoadValue, double verticalLoadValue)
        {
            //创建有限元模型
            var model = GetWModelNet(width, height, length, meshNumber);
            //创建有限元模型
            if (!model.CreateFEModel(false)) return model.ShowWarningError();

            //添加竖向力
            model.AddNodeLoad(1, 3, verticalLoadValue);
            model.AddNodeLoad(3, 3, verticalLoadValue);
            //求解竖向力
            if (!model.DoLinearStaticAnalyze()) return model.ShowWarningError();

            //添加水平力
            model.AddNodeLoad(1, 1, horizontalLoadValue);
            model.AddNodeLoad(3, 1, horizontalLoadValue);
            //求解
            if (!model.DoLinearStaticAnalyze()) return model.ShowWarningError();

            //显示结果
            return Show(model);
        }

        /// <summary>
        ///  悬臂柱算例 线性加载 一步进行（无法考虑二阶效应）
        /// </summary>
        /// <param name="width"> 截面宽度 </param>
        /// <param name="height"> 截面高度 </param>
        /// <param name="length"> 构件长度 </param>
        /// <param name="horizontalLoadValue"> 水平荷载 </param>
        /// <param name="verticalLoadValue"> 竖向荷载 </param>
        /// <returns></returns>
        public static bool PDeltaExampleWithSingleLinearAnalyze(double width, double height, double length, int meshNumber,
            double horizontalLoadValue, double verticalLoadValue)
        {
            //创建有限元模型
            var model = GetWModelNet(width, height, length, meshNumber);
            //创建有限元模型
            if (!model.CreateFEModel(false)) model.ShowWarningError();

            //添加竖向力
            model.AddNodeLoad(1, 3, verticalLoadValue);
            model.AddNodeLoad(3, 3, verticalLoadValue);
            //添加水平力
            model.AddNodeLoad(1, 1, horizontalLoadValue);
            model.AddNodeLoad(3, 1, horizontalLoadValue);
            //求解
            if (!model.DoLinearStaticAnalyze()) 
                return model.ShowWarningError();
            //显示结果
            return Show(model);
        }

        /// <summary>
        ///  悬臂柱算例 通用加载 一步进行
        /// </summary>
        /// <param name="width"> 截面宽度 </param>
        /// <param name="height"> 截面高度 </param>
        /// <param name="length"> 构件长度 </param>
        /// <param name="horizontalLoadValue"> 水平荷载 </param>
        /// <param name="verticalLoadValue"> 竖向荷载 </param>
        /// <returns></returns>
        public static bool PDeltaExampleWithSingleGeneralAnalyze(double width, double height, double length, int meshNumber,
            double horizontalLoadValue, double verticalLoadValue)
        {
            //创建有限元模型
            var model = GetWModelNet(width, height, length, meshNumber);
            //创建有限元模型
            if (!model.CreateFEModel(false)) model.ShowWarningError();

            //添加竖向力
            model.AddNodeLoad(1, 3, verticalLoadValue);
            model.AddNodeLoad(3, 3, verticalLoadValue);
            //添加水平力
            model.AddNodeLoad(1, 1, horizontalLoadValue);
            model.AddNodeLoad(3, 1, horizontalLoadValue);
            //求解
            if (!model.DoGeneralStaticAnalyze(1)) return model.ShowWarningError();
            //显示结果
            return Show(model);
        }

        /// <summary>
        /// 建立算例有限元模型
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        private static WModelNet GetWModelNet(double width, double height, double length, int meshNumber)
        {
            //不插值显示
            StructrueChart.FrameInterpolationPrtNum = 0;

            //初始化模型参数
            var model = new WModelNet();
            //添加节点
            model.AddNode(0, 0, 0, 0);
            model.AddNode(1, 0, 0, length);
            model.AddNode(2, 0, length, 0);
            model.AddNode(3, 0, length, length);
            //增加中间节点
            var deltaLength = length / meshNumber;
            for(int subElement = 1; subElement < meshNumber; subElement++)
                model.AddNode(3 + subElement, 0, length, subElement * deltaLength);
            //添加约束
            model.FixZ(0);
            //添加柱单元（柱默认考虑二阶效应）
            var element = model.AddRectConcreteColumn(0, 1, width, height);
            //节点编号
            var nodeTag = 2;
            //增加中央柱单元
            for (int subElement = 1; subElement < meshNumber; subElement++)
            {
                var jNode = subElement + 3;
                model.AddRectConcreteColumn(nodeTag, jNode, width, height);
                nodeTag = jNode;
            }
            //添加柱单元
            model.AddRectConcreteColumn(nodeTag, 3, width, height);
            //设定二阶效应
            element.SetPDelta(false);
            //返回模型
            return model;
        }

        /// <summary>
        /// 结果显示
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private static bool Show(WModelNet model)
        {
            //显示位移响应
            MessageBoxExtern.Asterisk(string.Format("不考虑二阶效应的顶点位移:{0}mm\n考虑二阶效应的顶点位移:{1}mm",
              model.GetNodeResponse(1, NodeResponseEnum.Disp, 1),
               model.GetNodeResponse(3, NodeResponseEnum.Disp, 1)), isDialog: false);
            //绘图
            model.ToGraphics(new StructrueChartParam(StructureChartType.GeneralStatic));
            return true;
        }
    }
}
